/*
 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <hi_task.h>
#include <string.h>
#include <hi_wifi_api.h>
#include <hi_mux.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include "iot_config.h"
#include "iot_log.h"
#include "iot_main.h"
#include "iot_profile.h"
#include "ohos_init.h"
#include "cmsis_os2.h"

#include <hi_types_base.h>
#include <hi_early_debug.h>
#include <hi_stdlib.h>
#include <hi_uart.h>
#include <app_demo_uart.h>
#include <iot_uart.h>
#include "iot_gpio_ex.h"
#include "iot_gpio.h"
#include "hisignalling_protocol.h"
#include "hi_time.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>


/* attribute initiative to report */
#define TAKE_THE_INITIATIVE_TO_REPORT
#define ONE_SECOND                          (1000)
/* oc request id */
#define CN_COMMADN_INDEX                    "commands/request_id="
/*#define WECHAT_SUBSCRIBE_LIGHT              "light"
#define WECHAT_SUBSCRIBE_LIGHT_ON_STATE     "1"
#define WECHAT_SUBSCRIBE_LIGHT_OFF_STATE    "0"*/

#define WECHAT_SUBSCRIBE_RECYCLE            "recycle"
#define WECHAT_SUBSCRIBE_RECYCLE_OFF_STATE  "1"
#define WECHAT_SUBSCRIBE_RECYCLE_ON_STATE   "0"

#define WECHAT_SUBSCRIBE_HARM               "harm"
#define WECHAT_SUBSCRIBE_HARM_OFF_STATE     "1"
#define WECHAT_SUBSCRIBE_HARM_ON_STATE      "0"

#define WECHAT_SUBSCRIBE_KITCHEN            "kitchen"
#define WECHAT_SUBSCRIBE_KITCHEN_OFF_STATE  "1"
#define WECHAT_SUBSCRIBE_KITCHEN_ON_STATE   "0"

#define WECHAT_SUBSCRIBE_OTHER              "other"
#define WECHAT_SUBSCRIBE_OTHER_OFF_STATE    "1"
#define WECHAT_SUBSCRIBE_OTHER_ON_STATE     "0"

#define COUNT 10

int g_ligthStatus = -1;
typedef void (*FnMsgCallBack)(hi_gpio_value val);

typedef struct FunctionCallback {
    hi_bool  stop;
    hi_u32 conLost;
    hi_u32 queueID;
    hi_u32 iotTaskID;
    FnMsgCallBack    msgCallBack;
}FunctionCallback;
FunctionCallback g_functinoCallback;

/* CPU Sleep time Set */
unsigned int TaskMsleep(unsigned int ms)
{
    if (ms <= 0) {
        return HI_ERR_FAILURE;
    }
    return hi_sleep((hi_u32)ms);
}

/*
static void DeviceConfigInit(hi_gpio_value val)
{
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
}
*/

void set_angle1(unsigned int duty,unsigned int gpiokou)
{   
    unsigned int time = 20000;
    IoTGpioSetDir(gpiokou, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(gpiokou, IOT_GPIO_VALUE1);
    hi_udelay(duty);
    IoTGpioSetOutputVal(gpiokou, IOT_GPIO_VALUE0);
    hi_udelay(time - duty);
}

void engine_turn_right_90_1(unsigned int gpiokou)
{
    unsigned int angle = 2500;
    for (int i = 0; i < COUNT; i++) {
        set_angle1(angle,gpiokou);
    }
}
void regress_middle_1(unsigned int gpiokou)
{
    unsigned int angle = 1500;
    for (int i = 0; i < COUNT; i++) 
    {
        set_angle1(angle,gpiokou);
    }
}
//可回收
static void DeviceConfigInit_open_recycle(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_10, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    engine_turn_right_90_1(10);
}
static void DeviceConfigInit_close_recycle(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_10, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    regress_middle_1(10);
}
//有害垃圾
static void DeviceConfigInit_open_harmful(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_12, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    engine_turn_right_90_1(12);
}
static void DeviceConfigInit_close_harmful(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_12, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    regress_middle_1(12);
}

//厨余垃圾
static void DeviceConfigInit_open_kitchen(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_11, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    engine_turn_right_90_1(11);
}
static void DeviceConfigInit_close_kitchen(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_11, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    regress_middle_1(11);
}

//其他垃圾
static void DeviceConfigInit_open_other(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_2, HI_IO_FUNC_GPIO_2_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_2, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    engine_turn_right_90_1(2);
}
static void DeviceConfigInit_close_other(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_2, HI_IO_FUNC_GPIO_2_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_2, HI_GPIO_DIR_OUT);
    //hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
    regress_middle_1(2);
}



static int  DeviceMsgCallback(FnMsgCallBack msgCallBack)
{
    g_functinoCallback.msgCallBack = msgCallBack;
    return 0;
}
/*
static void wechatControlDeviceMsg(hi_gpio_value val)
{
    DeviceConfigInit(val);
}
*/

// < this is the callback function, set to the mqtt, and if any messages come, it will be called
// < The payload here is the json string
static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)
{
    IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload);
    /* 云端下发命令后，板端的操作处理 */
    /*if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT_OFF_STATE) != NULL) {
            //wechatControlDeviceMsg(HI_GPIO_VALUE1);
            g_ligthStatus = HI_FALSE;
        } else {
            //wechatControlDeviceMsg(HI_GPIO_VALUE0);
            g_ligthStatus = HI_TRUE;
        }
    }*/
//可回收
    if (strstr(payload, WECHAT_SUBSCRIBE_RECYCLE ) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_RECYCLE_ON_STATE) == NULL) {
            DeviceConfigInit_open_recycle();
            g_ligthStatus = HI_TRUE;
        } else {
            DeviceConfigInit_close_recycle();
            g_ligthStatus = HI_FALSE;
        }
    }
    //有害垃圾
    if (strstr(payload, WECHAT_SUBSCRIBE_HARM ) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_HARM_OFF_STATE) != NULL) {
            DeviceConfigInit_close_harmful();
            g_ligthStatus = HI_FALSE;
        } else {
            DeviceConfigInit_open_harmful();
            g_ligthStatus = HI_TRUE;
        }
    }
    //厨余垃圾
    if (strstr(payload, WECHAT_SUBSCRIBE_KITCHEN ) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_KITCHEN_OFF_STATE) != NULL) {
            DeviceConfigInit_close_kitchen();
            g_ligthStatus = HI_FALSE;
        } else {
            DeviceConfigInit_open_kitchen();
            g_ligthStatus = HI_TRUE;
        }
    }
    //其他垃圾
    if (strstr(payload, WECHAT_SUBSCRIBE_OTHER ) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_OTHER_OFF_STATE) != NULL) {
            DeviceConfigInit_close_other();
            g_ligthStatus = HI_FALSE;
        } else {
            DeviceConfigInit_open_other();
            g_ligthStatus = HI_TRUE;
        }
    }

    return HI_NULL;
}

/* publish sample */
hi_void IotPublishSample(void)
{
    /* reported attribute */
    WeChatProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
        /* report motor */
        .reportAction.subDeviceActionMotor = "motor",
        .reportAction.motorActionStatus = 0, /* 0 : motor off */
        /* report temperature */
        .reportAction.subDeviceActionTemperature = "temperature",
        .reportAction.temperatureData = 78, /* 30 :temperature data */
        /* report humidity */
        .reportAction.subDeviceActionHumidity = "humidity",
        .reportAction.humidityActionData = 52, /* humidity data */
        /* report light_intensity */
        .reportAction.subDeviceActionLightIntensity = "light_intensity",
        .reportAction.lightIntensityActionData = 99, /* 60 : light_intensity */
    };

    /* report light */
    if (g_ligthStatus == HI_TRUE) {
        weChatProfile.reportAction.subDeviceActionLight = "light";
        weChatProfile.reportAction.lightActionStatus = 1; /* 1: light on */
    } else if (g_ligthStatus == HI_FALSE) {
        weChatProfile.reportAction.subDeviceActionLight = "light";
        weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */
    } else {
        weChatProfile.reportAction.subDeviceActionLight = "light";
        weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */
    }

    
    if (g_ligthStatus == HI_TRUE) {
        weChatProfile.reportAction.subDeviceActionLight = "recycle";
        weChatProfile.reportAction.lightActionStatus = 1; /* 1: light on */
    } else if (g_ligthStatus == HI_FALSE) {
        weChatProfile.reportAction.subDeviceActionLight = "recycle";
        weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */
    } else {
        weChatProfile.reportAction.subDeviceActionLight = "recycle";
        weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */
    }



    /* profile report */
    IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile);
}

// < this is the demo main task entry,here we will set the wifi/cjson/mqtt ready and
// < wait if any work to do in the while
static hi_void *DemoEntry(const char *arg)
{
    WifiStaReadyWait();
    cJsonInit();
    IoTMain();
    /* 云端下发回调 */
    IoTSetMsgCallback(DemoMsgRcvCallBack);
    /* 主动上报 */
#ifdef TAKE_THE_INITIATIVE_TO_REPORT
    while (1) {
        /* 用户可以在这调用发布函数进行发布，需要用户自己写调用函数 */
        IotPublishSample(); // 发布例程
#endif
        TaskMsleep(ONE_SECOND);
    }
    return NULL;
}

// < This is the demo entry, we create a task here,
// and all the works has been done in the demo_entry
#define CN_IOT_TASK_STACKSIZE  0x1000
#define CN_IOT_TASK_PRIOR 25
#define CN_IOT_TASK_NAME "IOTDEMO"

static void AppDemoIot(void)
{
    osThreadAttr_t attr;
    IoTWatchDogDisable();

    attr.name = "IOTDEMO";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = CN_IOT_TASK_STACKSIZE;
    attr.priority = CN_IOT_TASK_PRIOR;

    if (osThreadNew((osThreadFunc_t)DemoEntry, NULL, &attr) == NULL) {
        printf("[mqtt] Falied to create IOTDEMO!\n");
    }
}

SYS_RUN(AppDemoIot);